package fnsvr

import (
	"fmt"
	"io"
	"log/slog"
	"os"
	"sync"
	"time"
)

type Logger struct {
	logger  *slog.Logger
	logFile *LoggerWriter
}

func (l *Logger) Inst() *slog.Logger {
	return l.logger
}

func (l *Logger) Destroy() {
	l.logger = nil
	if l.logFile != nil {
		l.logFile.Close()
	}
}

// 创建日志输出工具
func NewLogger(isDev bool, logPath string, logPrefix string) (*Logger, error) {

	re := &Logger{}

	level := slog.LevelDebug
	if !isDev {
		level = slog.LevelInfo
	}

	var w io.Writer = os.Stdout

	if !isDev {
		logFile := NewLoggerWriter(logPath, logPrefix)

		re.logFile = logFile
		w = io.MultiWriter(os.Stdout, logFile)
	}

	logger := slog.New(slog.NewJSONHandler(w, &slog.HandlerOptions{
		Level:     level, // 显示 level 及以上级别
		AddSource: true,  // 记录源代码位置
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			// 自定义时间格式
			if a.Key == slog.TimeKey {
				return slog.String("timestamp", a.Value.Time().Format("2006-01-02 15:04:05"))
			}
			/*
				// 重命名 level 为 severity
				if a.Key == slog.LevelKey {
					a.Key = "severity"
				}*/
			return a
		},
	}))

	re.logger = logger

	return re, nil
}

// 日志writer
type LoggerWriter struct {
	mu      sync.RWMutex
	weekday time.Weekday
	fh      *os.File
	logPath string
	prefix  string //文件名前缀
}

func (l *LoggerWriter) _autoCreateFile() error {
	t := time.Now()
	if l.weekday != t.Weekday() {
		l.weekday = t.Weekday()
		if l.fh != nil {
			l.fh.Close()
		}
		name := fmt.Sprintf("%s/%s_%s.log", l.logPath, l.prefix, t.Format("2006-01-02"))
		fh, err := os.OpenFile(name, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
		if err != nil {
			return err
		}
		l.fh = fh
	}
	return nil
}

func (l *LoggerWriter) Write(p []byte) (int, error) {
	l.mu.Lock()
	defer l.mu.Unlock()

	l._autoCreateFile()
	wlen, err := l.fh.Write(p)
	if err != nil {
		l.weekday = 0
		l._autoCreateFile()
		wlen, err = l.fh.Write(p)
	}
	return wlen, err
}

func (l *LoggerWriter) Close() error {
	if l.fh != nil {
		return l.fh.Close()
	}
	return nil
}

var g_logger *Logger

// 创建日志writer
func NewLoggerWriter(logPath string, prefix string) *LoggerWriter {
	return &LoggerWriter{
		logPath: logPath,
		prefix:  prefix,
	}
}

// 设置缺省日志
func SetDefaultLogger(logger *Logger) {
	g_logger = logger
}

func init() {
	SetDefaultLogger(&Logger{
		logger: slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
			Level:     slog.LevelDebug,
			AddSource: true,
		})),
		logFile: nil,
	})
}

// 获取日志工具
func Log() *slog.Logger {
	return g_logger.Inst()
}
